#pragma once
#include "NetWork.hpp"
using namespace Network;

namespace ComProtocol {
	enum OperationType
	{
		Normal,
		Login,
		GetList,
		GetInfor,
		SendTo,
		GlobalMsg,
		Quiet
	};

	class UserList {
	public:
		string ID;
		HSocket User;

		void SubDo(shared_ptr<DataStream> dm)
		{
			dm->DoObj<HSocket>(User);
			dm->DoObj<string>(ID);
		}

		UserList(string ID_,HSocket User_)
		{
			ID = ID_; User = User_;
		}
		UserList()
		{

		}
	};

	namespace Send {
		class Template {
		public:
			shared_ptr<DataStream>  Pack() {
				shared_ptr<DataStream> dm(new DataStream());
				OperationType otype = OperationType::Normal;
				dm->DoObj<OperationType>(otype);
				//first pack the type of operation

				//this can pack your own values
				return dm;
			}
			Template() {

			}
			Template(shared_ptr<DataStream> dm) {

			}
			~Template() {
			}
		};

		class Login {
		public:
			string ID;
			string PWD;

			shared_ptr<DataStream>  Pack() {
				shared_ptr<DataStream> dm(new DataStream());
				OperationType otype = OperationType::Login;
				dm->DoObj<OperationType>(otype);

				dm->DoObj<string>(ID);
				dm->DoObj<string>(PWD);
				return dm;
			}
			Login(string ID_, string PWD_) {
				ID = ID_;
				PWD = PWD_;
			}
			Login(shared_ptr<DataStream> dm) {//Unpack
				dm->DoObj<string>(ID);
				dm->DoObj<string>(PWD);
			}
		};

		class GetList {
		public:

			shared_ptr<DataStream> Pack() {
				shared_ptr<DataStream> dm(new DataStream());
				OperationType otype = OperationType::GetList;
				dm->DoObj<OperationType>(otype);

				return dm;
			}
			GetList() {
			}
			GetList(shared_ptr<DataStream> dm) {//Unpack
			}
		};

		class GlobalMsg {
		public:
			string msg;

			shared_ptr<DataStream>  Pack() {
				shared_ptr<DataStream> dm(new DataStream());
				OperationType otype = OperationType::GlobalMsg;
				dm->DoObj<OperationType>(otype);
				//first pack the type of operation
				dm->DoObj<string>(msg);
				//this can pack your own values
				return dm;
			}
			GlobalMsg(string msg_) {
				//this can auto copy values by init repnction
				msg = msg_;
			}
			GlobalMsg(shared_ptr<DataStream> dm) {
				dm->DoObj<string>(msg);
			}
			~GlobalMsg() {
				//you must delete all points you newed
			}
		};

		class SendTo {
		public:
			HSocket target_cli;
			shared_ptr<DataStream> withstream;

			shared_ptr<DataStream>  Pack() {
				shared_ptr<DataStream> dm(new DataStream());
				OperationType otype = OperationType::SendTo;
				dm->DoObj<OperationType>(otype);

				dm->DoObj<HSocket>(target_cli);
				string tmp=withstream->GetSrc();
				dm->DoObj<string>(tmp);
				return dm;
			}
			SendTo(shared_ptr<DataStream> withstream_, HSocket taget_) {
				withstream = withstream_;
				target_cli = taget_;
			}
			SendTo(shared_ptr<DataStream> dm) {//unpack
				dm->DoObj<HSocket>(target_cli);

				string tmp = "";
				dm->DoObj<string>(tmp);
				withstream.reset(new DataStream(tmp));
			}
			~SendTo() {
			}
		};
	}
	namespace Recv {
		class Login {
		public:
			bool Return;

			shared_ptr<DataStream> Pack() {
				shared_ptr<DataStream> dm(new DataStream());
				OperationType otype = OperationType::Login;
				dm->DoObj<OperationType>(otype);

				dm->DoObj<bool>(Return);
				return dm;
			}
			Login(bool Return_) {
				Return = Return_;
			}
			Login(shared_ptr<DataStream> dm) {//Unpack
				dm->DoObj<bool>(Return);
			}
		};

		class GetList {
		public:
			//shared_ptr<FightList> FightList_;
			shared_ptr<map<HSocket, UserList> > UserList_;

			shared_ptr<DataStream> Pack() {
				shared_ptr<DataStream> dm(new DataStream());
				OperationType otype = OperationType::GetList;
				dm->DoObj<OperationType>(otype);

				int cnt = UserList_->size();
				dm->DoObj<int>(cnt);
				for (pair<const HSocket, UserList> & tmp_ : *UserList_)
				{
					tmp_.second.SubDo(dm);
				}//WARN:a list of class can't be do once.must creat a sub do
				return dm;
			}
			GetList(shared_ptr<map<HSocket, UserList> > UserList__) {
				UserList_ = UserList__;
			}
			GetList(shared_ptr<DataStream> dm) {//Unpack
				UserList_.reset(new map<HSocket, UserList>());

				//needdelete = true;

				int cnt = 0;
				UserList tmp_;

				dm->DoObj<int>(cnt);
				rep(i, 1, cnt)
				{
					tmp_.SubDo(dm);
					UserList_->insert(pair<HSocket, UserList>(tmp_.User, tmp_));
				}//WARN:a list of class can't be do once.must creat a sub do
				 //dm->DoList<FightList>(FightList_);
			}

			~GetList() {
				//if (needdelete && FightList_ != nullptr)delete FightList_;
			}
		private:
			//bool needdelete = false;//WARN:don't delete pointer from sever!
		};

		class GlobalMsg {
		public:
			string ID;
			string msg;

			shared_ptr<DataStream>  Pack() {
				shared_ptr<DataStream> dm(new DataStream());
				OperationType otype = OperationType::GlobalMsg;
				dm->DoObj<OperationType>(otype);
				//first pack the type of operation
				dm->DoObj<string>(ID);
				dm->DoObj<string>(msg);
				//this can pack your own values
				return dm;
			}
			GlobalMsg(string id_,string msg_) {
				//this can auto copy values by init repnction
				msg = msg_;
				ID = id_;
			}
			GlobalMsg(shared_ptr<DataStream> dm) {
				dm->DoObj<string>(ID);
				dm->DoObj<string>(msg);
			}
			~GlobalMsg() {
				//you must delete all points you newed
			}
		};

		class SendTo {
		public:
			HSocket from_cli;
			shared_ptr<DataStream> withstream;

			shared_ptr<DataStream>  Pack() {
				shared_ptr<DataStream> dm(new DataStream());
				OperationType otype = OperationType::SendTo;
				dm->DoObj<OperationType>(otype);

				dm->DoObj<HSocket>(from_cli);
				string tmp=withstream->GetSrc();
				dm->DoObj<string>(tmp);
				return dm;
			}
			SendTo(shared_ptr<DataStream> withstream_, HSocket from_) {
				withstream = withstream_;
				from_cli = from_;
			}
			SendTo(shared_ptr<DataStream> dm) {
				dm->DoObj<HSocket>(from_cli);

				string tmp = "";
				dm->DoObj<string>(tmp);
				withstream.reset(new DataStream(tmp));
			}
			~SendTo() {
			}
		};
	}
}
